﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using UnityEngine;
using Voxel2Unity;

public static class VoxelImporter
{
    [CompilerGenerated]
    private static Func<KeyValuePair<int, VoxMaterial>, bool> <>f__am$cache1;
    [CompilerGenerated]
    private static Func<KeyValuePair<int, VoxMaterial>, int> <>f__am$cache2;
    [CompilerGenerated]
    private static Func<KeyValuePair<int, VoxMaterial>, VoxMaterial> <>f__am$cache3;
    [CompilerGenerated]
    private static Func<KeyValuePair<int, VoxMaterial>, bool> <>f__am$cache4;
    [CompilerGenerated]
    private static Func<KeyValuePair<int, VoxMaterial>, int> <>f__am$cache5;
    [CompilerGenerated]
    private static Func<KeyValuePair<int, VoxMaterial>, VoxMaterial> <>f__am$cache6;
    [CompilerGenerated]
    private static Func<KeyValuePair<int, VoxMaterial>, bool> <>f__am$cache7;
    [CompilerGenerated]
    private static Func<KeyValuePair<int, VoxMaterial>, bool> <>f__am$cache8;
    public static float importScale = 0.06666667f;

    private static GameObject CreateModel(VoxData chunk, Vector3 pivot, float scale, Dictionary<int, VoxMaterial> materials)
    {
        <CreateModel>c__AnonStorey79 storey = new <CreateModel>c__AnonStorey79 {
            chunk = chunk
        };
        if (storey.chunk.VoxelNum == 0)
        {
            return new GameObject("Model");
        }
        Mesh[] meshs = null;
        Texture2D texture = null;
        VoxelMesh mesh = new VoxelMesh();
        mesh.CreateVoxelMesh(storey.chunk, scale, pivot, ref meshs, ref texture);
        bool flag = false;
        if (((meshs == null) || (texture == null)) || (mesh == null))
        {
            flag = true;
        }
        else
        {
            foreach (Mesh mesh2 in meshs)
            {
                if (mesh2 == null)
                {
                    flag = true;
                    break;
                }
            }
        }
        if (flag)
        {
            return null;
        }
        int length = meshs.Length;
        GameObject obj2 = new GameObject("Model");
        GameObject[] objArray = new GameObject[length];
        Material material = new Material(Shader.Find("Standard"));
        texture.name = "Texture";
        material.mainTexture = texture;
        material.name = "Material";
        material.SetFloat("_Glossiness", 0f);
        if (materials.Count > 0)
        {
            if (<>f__am$cache7 == null)
            {
                <>f__am$cache7 = x => x.Value.materialType == VoxMaterial.Type.emissive;
            }
            Color[] colorArray = materials.Where<KeyValuePair<int, VoxMaterial>>(<>f__am$cache7).Select<KeyValuePair<int, VoxMaterial>, Color>(new Func<KeyValuePair<int, VoxMaterial>, Color>(storey.<>m__148)).ToArray<Color>();
            if (colorArray.Length > 0)
            {
                Texture2D textured2 = UnityEngine.Object.Instantiate<Texture2D>(texture);
                Color[] pixels = texture.GetPixels();
                material.SetTexture("_EmissionMap", textured2);
                material.SetColor("_EmissionColor", Color.white);
                material.EnableKeyword("_EMISSION");
                Color[] colors = textured2.GetPixels();
                for (int j = 0; j < colors.Length; j++)
                {
                    colors[j] = Color.clear;
                }
                for (int k = 0; k < pixels.Length; k++)
                {
                    foreach (Color color in colorArray)
                    {
                        if (pixels[k].Equals(color.SetA(1f)))
                        {
                            colors[k] = (Color) (pixels[k] * color.a);
                        }
                    }
                }
                textured2.SetPixels(colors);
                textured2.Apply();
            }
            if (<>f__am$cache8 == null)
            {
                <>f__am$cache8 = x => x.Value.materialType == VoxMaterial.Type.glass;
            }
            Color[] colorArray5 = materials.Where<KeyValuePair<int, VoxMaterial>>(<>f__am$cache8).Select<KeyValuePair<int, VoxMaterial>, Color>(new Func<KeyValuePair<int, VoxMaterial>, Color>(storey.<>m__14A)).ToArray<Color>();
            if (colorArray5.Length > 0)
            {
                material.SetStandardAsTransparent();
                Color[] colorArray6 = texture.GetPixels();
                for (int m = 0; m < colorArray6.Length; m++)
                {
                    foreach (Color color2 in colorArray5)
                    {
                        if (colorArray6[m].Equals(color2.SetA(1f)))
                        {
                            colorArray6[m].a = color2.a;
                        }
                    }
                }
                texture.SetPixels(colorArray6);
                texture.Apply();
            }
        }
        for (int i = 0; i < length; i++)
        {
            objArray[i] = new GameObject("Mesh_" + i);
            objArray[i].transform.SetParent(obj2.transform);
            MeshFilter filter = objArray[i].AddComponent<MeshFilter>();
            MeshRenderer renderer = objArray[i].AddComponent<MeshRenderer>();
            meshs[i].name = "Mesh_" + i;
            filter.mesh = meshs[i];
            renderer.material = material;
        }
        mesh = null;
        return obj2;
    }

    public static void CreateModelPrefab(string voxelPath, string outputPath, Vector3 pivot, float scale)
    {
    }

    public static void CreateObj(string voxFilePath, string outputPath, Vector3 pivot, float scale)
    {
        voxFilePath = Util.FixPath(voxFilePath);
        string extension = Path.GetExtension(voxFilePath);
        switch (extension)
        {
            case ".vox":
            case ".qb":
                VoxData voxData;
                if (extension == ".vox")
                {
                    voxData = VoxFile.LoadVoxel(voxFilePath);
                }
                else
                {
                    voxData = QbFile.LoadQb(voxFilePath).GetVoxData();
                }
                if (voxData != null)
                {
                    VoxelMesh mesh = new VoxelMesh();
                    Texture2D texture = null;
                    string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(voxFilePath);
                    string objFile = fileNameWithoutExtension;
                    try
                    {
                        mesh.CreateVoxelMesh(voxData, scale, pivot, ref texture, ref objFile);
                    }
                    catch (Exception exception)
                    {
                        Debug.LogError("ERROR Failed to Create obj file for " + Path.GetFileNameWithoutExtension(voxFilePath) + ". " + exception.Message);
                        return;
                    }
                    if (string.IsNullOrEmpty(objFile))
                    {
                        Debug.LogError("ERROR Failed to Create model for " + fileNameWithoutExtension + ". Can not create mesh or texture.");
                        return;
                    }
                    string fileName = Util.FixPath(outputPath);
                    string fullName = new FileInfo(fileName).Directory.FullName;
                    Util.CreateFolder(fullName);
                    Util.Save(objFile, fileName);
                    if (texture != null)
                    {
                        Util.CreateFolder(fullName);
                        string path = fullName + "/" + fileNameWithoutExtension + ".png";
                        Util.ByteToFile(texture.EncodeToPNG(), path);
                    }
                }
                else
                {
                    Debug.LogError("[Voxel To Unity]Can not load file:" + voxFilePath);
                }
                break;
        }
    }

    public static GameObject Load(string _path)
    {
        return Load(_path, new Vector3(0.5f, 0f, 0.5f));
    }

    public static GameObject Load(string _path, Vector3 pivot)
    {
        return Load(_path, pivot, 0.01f);
    }

    public static GameObject Load(string path, Vector3 pivot, float scale)
    {
        Dictionary<int, VoxMaterial> dictionary;
        if (Path.GetExtension(path) != ".vox")
        {
            return null;
        }
        List<VoxData> list = VoxFileExt.LoadVoxel(path, out dictionary);
        if (<>f__am$cache1 == null)
        {
            <>f__am$cache1 = x => x.Value.materialType != VoxMaterial.Type.glass;
        }
        if (<>f__am$cache2 == null)
        {
            <>f__am$cache2 = x => x.Key;
        }
        if (<>f__am$cache3 == null)
        {
            <>f__am$cache3 = x => x.Value;
        }
        Dictionary<int, VoxMaterial> materials = dictionary.Where<KeyValuePair<int, VoxMaterial>>(<>f__am$cache1).ToDictionary<KeyValuePair<int, VoxMaterial>, int, VoxMaterial>(<>f__am$cache2, <>f__am$cache3);
        if (<>f__am$cache4 == null)
        {
            <>f__am$cache4 = x => x.Value.materialType == VoxMaterial.Type.glass;
        }
        if (<>f__am$cache5 == null)
        {
            <>f__am$cache5 = x => x.Key;
        }
        if (<>f__am$cache6 == null)
        {
            <>f__am$cache6 = x => x.Value;
        }
        Dictionary<int, VoxMaterial> dictionary3 = dictionary.Where<KeyValuePair<int, VoxMaterial>>(<>f__am$cache4).ToDictionary<KeyValuePair<int, VoxMaterial>, int, VoxMaterial>(<>f__am$cache5, <>f__am$cache6);
        if (list == null)
        {
            Debug.LogError("Failed to Load Vox file : " + path);
            return null;
        }
        GameObject obj2 = new GameObject();
        string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
        obj2.name = fileNameWithoutExtension;
        for (int i = 0; i < list.Count; i++)
        {
            VoxData chunk = list[i];
            VoxData data2 = null;
            if (dictionary3.Count > 0)
            {
                data2 = new VoxData {
                    Name = chunk.Name,
                    Palatte = chunk.Palatte,
                    Voxels = new int[chunk.SizeX, chunk.SizeY, chunk.SizeZ],
                    SizeX = chunk.SizeX,
                    SizeY = chunk.SizeY,
                    SizeZ = chunk.SizeZ
                };
                for (int j = 0; j < chunk.SizeX; j++)
                {
                    for (int k = 0; k < chunk.SizeY; k++)
                    {
                        for (int m = 0; m < chunk.SizeZ; m++)
                        {
                            if (dictionary3.ContainsKey(chunk.Voxels[j, k, m]))
                            {
                                data2.Voxels[j, k, m] = chunk.Voxels[j, k, m];
                                chunk.Voxels[j, k, m] = 0;
                            }
                        }
                    }
                }
            }
            GameObject obj3 = CreateModel(chunk, pivot, scale, materials);
            if (obj3 == null)
            {
                Debug.LogError("ERROR : Failed to Create model for " + fileNameWithoutExtension + ". Can not create mesh or texture.");
            }
            else
            {
                obj3.name = "Frame_" + i;
                obj3.transform.parent = obj2.transform;
                if (data2 != null)
                {
                    GameObject obj4 = CreateModel(data2, pivot, scale, dictionary3);
                    obj4.name = "TransparentPart";
                    obj4.transform.parent = obj3.transform;
                }
            }
        }
        if (obj2.transform.childCount > 1)
        {
            FrameAnimator animator = obj2.AddComponent<FrameAnimator>();
            FrameAnimator.Clip clip = new FrameAnimator.Clip("Default", true);
            for (int n = 0; n < obj2.transform.childCount; n++)
            {
                clip.AddFrame(obj2.transform.GetChild(n).gameObject, 0.1f);
            }
            animator.AddClip(clip);
            animator.playOnEnable = true;
        }
        return obj2;
    }

    [CompilerGenerated]
    private sealed class <CreateModel>c__AnonStorey79
    {
        internal VoxData chunk;

        internal Color <>m__148(KeyValuePair<int, VoxMaterial> x)
        {
            return this.chunk.Palatte[x.Key - 1].SetA(x.Value.materialWeight);
        }

        internal Color <>m__14A(KeyValuePair<int, VoxMaterial> x)
        {
            return this.chunk.Palatte[x.Key - 1].SetA((1f - x.Value.materialWeight));
        }
    }
}

